package cn.lg.soar.mvc.config;

import cn.lg.soar.common.data.msg.I18n;
import cn.lg.soar.common.exceptions.BaseAException;
import cn.lg.soar.common.exceptions.ParameterException;
import cn.lg.soar.common.model.HttpResult;
import cn.lg.soar.common.util.data.DataUtil;
import cn.lg.soar.common.util.data.StringUtil;
import cn.lg.soar.core.handler.ex.ErrorResult;
import cn.lg.soar.core.handler.ex.SoarExceptionHandler;
import org.apache.tomcat.util.http.fileupload.impl.SizeException;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartException;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 全局拦截异常处理异常
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
@Configuration
public class MvcExceptionHandleConfig extends SoarExceptionHandler {

    static {
        // 文件上传
        SoarExceptionHandler.register(MultipartException.class, exception -> {
            return new ErrorResult(400, HttpResult.fail(new BaseAException(10, I18n.build("文件上传异常"))));
        });
        // 文件大小
        SoarExceptionHandler.register(MaxUploadSizeExceededException.class, exception -> {
            String message = exception.getMessage();
            message = message.substring(message.length() - 20);
            message = StringUtil.getNumber(message);
            message = DataUtil.fileSizeFormat(DataUtil.toLong(message));
            return new ErrorResult(400, HttpResult.fail(new BaseAException(13, I18n.build("文件过大，限制{0}"), message)));
        });
        SoarExceptionHandler.register(SizeException.class, exception -> {
            String message = exception.getMessage();
            message = message.substring(message.length() - 20);
            message = StringUtil.getNumber(message);
            message = DataUtil.fileSizeFormat(DataUtil.toLong(message));
            return new ErrorResult(400, HttpResult.fail(new BaseAException(13, I18n.build("文件过大，限制{0}"), message)));
        });
        // 请求方式
        SoarExceptionHandler.register(HttpRequestMethodNotSupportedException.class, exception -> {
            HttpRequestMethodNotSupportedException e = (HttpRequestMethodNotSupportedException) exception;
            return new ErrorResult(405, HttpResult.fail(new BaseAException(0, I18n.build("仅支持 {0} 请求"), (Object[]) e.getSupportedMethods())));
        });

        // 缺少必要参数
        SoarExceptionHandler.register(
                MissingServletRequestParameterException.class,
                ex -> new ErrorResult(400, HttpResult.fail(new ParameterException(101, I18n.build("缺少必要参数"))))
        );
        // 数据不可读
        SoarExceptionHandler.register(HttpMessageNotReadableException.class, exception -> {
            String message = exception.getMessage();
            if (message.indexOf("JSON parse error: Cannot deserialize value of type ") == 0) {
                message = message.replace("JSON parse error: Cannot deserialize value of type ", "");
                message = message.substring(0, message.indexOf(": not a valid"));
                String[] split = message.split(" from ");
                message = split[1];
                message = split[1].substring(message.indexOf(" " + 1));
                ParameterException ex = new ParameterException(101, I18n.build("{0}不能转换为{1}类型"), message, split[0]);
                return new ErrorResult(400, HttpResult.fail(ex));
            }
            return new ErrorResult(400, HttpResult.fail(new ParameterException(101, I18n.build("数据不全或格式类型不正确"))));
        });
        // 参数校验
        SoarExceptionHandler.register(MethodArgumentNotValidException.class, exception -> {
            MethodArgumentNotValidException e = (MethodArgumentNotValidException) exception;
            BindingResult result = e.getBindingResult();
            List<FieldError> fieldErrors = result.getFieldErrors();
            Map<String, String> map = new HashMap<>(fieldErrors.size());
            for (FieldError fieldError : fieldErrors) {
                map.put(fieldError.getField(), fieldError.getDefaultMessage());
            }
            HttpResult<Map<String, String>> fail = HttpResult.fail(
                    new ParameterException(I18n.build("MethodArgumentNotValid", String.join("；", map.values())))
            );
            fail.setData(map);
            return new ErrorResult(400, fail);
        });
    }

    /**
     * 初始化
     */
    public static void init() {}

}
